package cn.bugstack.mybatis.session.defaults;

import cn.bugstack.mybatis.bindings.MapperRegistry;
import cn.bugstack.mybatis.mapping.Environment;
import cn.bugstack.mybatis.mapping.MappedStatement;
import cn.bugstack.mybatis.session.Configuration;
import cn.bugstack.mybatis.session.SqlSession;

import javax.sql.DataSource;
import java.lang.reflect.Method;
import java.sql.*;
import java.util.ArrayList;
import java.util.List;

public class DefaultSqlSession implements SqlSession {


    private final Configuration configuration;

    public DefaultSqlSession(Configuration configuration) {
        this.configuration = configuration;
    }

    @Override
    public <T> T selectOne(String statement) {
        return null;
    }

    @Override
    public <T> T selectOne(String statement, Object parameter) throws Exception {
        MappedStatement mappedStatement = configuration.getMappedStatement(statement);
        String resultType = mappedStatement.getResultType();
        String sql = mappedStatement.getSql();
        Environment environment = configuration.getEnvironment();
        DataSource datasource = environment.getDataSource();
        Connection connection = datasource.getConnection();
        PreparedStatement preparedStatement = connection.prepareStatement(sql);
        preparedStatement.setInt(1,Integer.valueOf(((Object[])parameter)[0].toString()));
        ResultSet resultSet = preparedStatement.executeQuery();
        ResultSetMetaData metaData = resultSet.getMetaData();
        int columnCount = metaData.getColumnCount();
        List<T> list = new ArrayList();
        while (resultSet.next()) {
            Class<?> clazz = Class.forName(resultType);
            T result = (T) clazz.newInstance();
            for (int i = 1; i <= columnCount; i++) {
                Object value = resultSet.getObject(i);
                String columnName = metaData.getColumnName(i);
                String setMethodName = "set" + columnName.substring(0, 1).toUpperCase() + columnName.substring(1);
                Method setMethod = clazz.getMethod(setMethodName,value.getClass());
                setMethod.invoke(result, value);
            }
            list.add(result);

        }
        return list.get(0);
    }

    @Override
    public <T> T getMapper(Class<T> type) {
        return configuration.getMapper(type,this);
    }

    @Override
    public Configuration getConfiguration() {
        return configuration;
    }
}
